package com.lm.leakybucket.example;

import java.util.concurrent.atomic.AtomicInteger;

public class LeakyBucketExample {

    private final int capacity;      // 漏桶的容量
    private final int rate;          // 漏出的速率 (每秒处理请求数)
    private AtomicInteger water;     // 当前桶中水的量
    private long lastTimestamp;      // 上次流出的时间

    public LeakyBucketExample(int capacity, int rate) {
        this.capacity = capacity;
        this.rate = rate;
        this.water = new AtomicInteger(0);
        this.lastTimestamp = System.currentTimeMillis();
    }

    public synchronized boolean grantAccess() {
        // 计算当前时间距离上次流出的时间间隔
        long currentTime = System.currentTimeMillis();
        long elapsed = currentTime - lastTimestamp;

        // 根据流出速率减少桶中的水量
        int leaked = (int) (elapsed * rate / 1000);
        if (leaked > 0) {
            water.addAndGet(-Math.min(leaked, water.get()));
            lastTimestamp = currentTime;
        }

        // 检查是否还有容量可以添加请求
        if (water.get() < capacity) {
            water.incrementAndGet();
            return true;  // 请求被接受
        } else {
            return false; // 请求被拒绝
        }
    }

    public static void main(String[] args) throws InterruptedException {
        LeakyBucketExample bucket = new LeakyBucketExample(10, 2); // 容量为10，每秒处理2个请求

        for (int i = 0; i < 15; i++) {
            if (bucket.grantAccess()) {
                System.out.println("请求 " + i + " 被接受");
            } else {
                System.out.println("请求 " + i + " 被拒绝");
            }
            Thread.sleep(100); // 每隔100ms发送一个请求
        }
    }
}
